package controller;

import java.util.List;

import javax.swing.JPanel;

import model.Project;
import modelInterfaces.IProject;
import pluginInterfaces.IRecommender;
import pluginInterfaces.setup.RecommenderSetup;
import utils.Codes;
import utils.Messages;
import utils.weka.core.SerializedObject;
import utils.weka.view.GenericObjectEditor;
import view.ViewRecommendersPanel;
import viewInterfaces.AbstractViewFactory;
import viewInterfaces.IViewRecommendersPanel;
import controllerInterfaces.IControllerMain;
import controllerInterfaces.IControllerRecommendersPanel;

/**
 * Controls flow of information from panel of recommendation algorithms configurations (Recommenders Panel)   
 */
public class ControllerRecommendersPanel implements IControllerRecommendersPanel {

	/** MVC++ Main Controller
	* @see ControllerMain*/
	private IControllerMain controllerMain;
	
	/** View of Panel of Recommenders
	 * @see ViewRecommendersPanel*/
	private IViewRecommendersPanel view;
	
	/** Index of selected item from View
	 * @see ViewRecommendersPanel*/
	private int indexToEdit;
	
	/**
	 * Class Constructor */
	public ControllerRecommendersPanel(){
		this.view = AbstractViewFactory.getAbstractViewFactory().getViewRecommendersPanel();
		this.view.SetController(this);
	}
	
	
	/**
	 * Set the MVC++ Main Class for this controller.</br>
	 * ControllerMain is manipulable through {@link IControllerMain} interface.
	 * @param	controllerMain	MVC++ Main Controller.
	 * @see	ControllerMain
	 * @see IControllerMain
	 */
	public void SetMainController(IControllerMain controllerMain) {
		this.controllerMain = controllerMain;
	}

	
	/**
	 * Get the Panel of View.
	 * @return Panel of Recommenders.
	 * @see ViewRecommendersPanel
	 */
	public JPanel getPanel() {
		return this.view.GetPanel();
	}


	/**
	 * Start the recommender setup for add a recommendation algorithm configuration ({@link Recommender}) from Recommenders Panel.
	 * @see Recommender
	 * @see IRecommender
	 */
	public void addRecommenderSetup() {
		
		if (controllerMain.getDBConnectedStatus())
		{
			GenericObjectEditor.registerEditors();
			GenericObjectEditor goe = new GenericObjectEditor(false, this, false);
			goe.setClassType(IRecommender.class);
			Object initial = new RecommenderSetup();
			goe.setValue(initial);
			this.view.renderDialogSetup(goe);
		}
		else
		{
			view.renderError(Codes.DBconnectionDoesntExist, Messages.DBconnectionDoesntExist);
		}
	}

	
	/**
	 * Start the recommender setup for edit a selected recommendation algorithm configuration ({@link Recommender}) from Recommenders Panel.
	 * @param	index	index of selected recommendation algorithm configuration.
	 * @see		Recommender
	 * @see		IRecommender
	 */	
	public void editRecommenderSetup(int index) {
		if (controllerMain.getDBConnectedStatus())
		{
			this.indexToEdit = index;
			GenericObjectEditor.registerEditors();
			GenericObjectEditor goe = new GenericObjectEditor(false, this, true);
			goe.setClassType(IRecommender.class);
			goe.setValue(this.controllerMain.getRecommenderList().get(
					this.indexToEdit));
			this.view.renderDialogSetup(goe);
		}
		else
		{
			view.renderError(Codes.DBconnectionDoesntExist, Messages.DBconnectionDoesntExist);
		}
	}	
	
	
	/**
	 * Remove the selected recommender setup from Recommenders Panel.
	 * @param	index	index of selected recommendation algorithm configuration.
	 * @see 	Project
	 * @see		IProject
	 */
	public void removeRecommenderSetup(int index) {
		this.controllerMain.removeAlgorithmIntoTest(index);
		this.controllerMain.getProject().getRecommenderList().remove(index);
		this.controllerMain.StatusProjectModified();
		this.view.setRecommenderList(this.controllerMain.getProject().getRecommenderList());
	}	


	/**
	 * Copy the selected recommender setup from Recommender Panel.
	 * @param	index	index of selected recommendation algorithm configuration.
	 * @see 	Project
	 * @see		IProject
	 */	
	public void copyRecommenderSetup(int index) {
		IRecommender recommenderOrig = this.controllerMain.getProject().getRecommenderList().get(index);
		IRecommender recommenderCopy = null;
		
	    try
	    {
	    	SerializedObject so = new SerializedObject(recommenderOrig);
	    	recommenderCopy = (IRecommender) so.getObject();
		}
	    catch (Exception e)
	    {
			e.printStackTrace();
		}
	    
	    recommenderCopy.setName(recommenderOrig.getName() + " - Copy of");
		this.addRecommender(recommenderCopy);
	}
	
	
	/**
	 * Add the recommender setup ({@link Recommender}) by using Weka object.
	 * @param	m_Object	Object generated by Weka.
	 * @see		GenericObjectEditor
	 * @see 	Project
	 * @see		IProject
	 */
	public void addRecommender(Object m_Object) {		
		this.controllerMain.getProject().getRecommenderList().add((IRecommender) m_Object);
		this.controllerMain.StatusProjectModified();
		this.view.setRecommenderList(this.controllerMain.getProject().getRecommenderList());
	}
	
	
	/**
	 * Add the recommender setup ({@link Recommender}) to realize a copy.
	 * @param	recommender	Recommender setup to be copied.
	 * @see		Recommender
	 * @see		IRecommender
	 * @see 	Project
	 * @see		IProject
	 */
	private void addRecommender(IRecommender recommender)
	{
		this.controllerMain.getProject().getRecommenderList().add(recommender);
		this.view.setRecommenderList(this.controllerMain.getProject().getRecommenderList());		
		this.controllerMain.StatusProjectModified();
	}	

	
	/**
	 * Add the edited recommender setup ({@link Recommender}) by using Weka object.
	 * @param	m_Object	Object generated by Weka.
	 * @see		GenericObjectEditor
	 * @see 	Project
	 * @see		IProject
	 */	
	public void editRecommender(Object m_Object) {
		
		IRecommender prNew = (IRecommender) m_Object;
		IRecommender prOld = this.controllerMain.getProject().getRecommenderList().get(this.indexToEdit);
		prOld.setName(prNew.getName());
		
		this.controllerMain.getProject().getRecommenderList().set(this.indexToEdit, prOld);
		this.controllerMain.StatusProjectModified();
		this.view.setRecommenderList(this.controllerMain.getProject().getRecommenderList());
	}
	
	
	/**
	 * Starts the Recommendation Algorithm Run Setup.
	 *  @param	selectedIndex	index of selected recommendation algorithm configuration from Recommender Panel.
	 */
	public void startRun(int selectedIndex) {
		this.controllerMain.startRunSetup(this.controllerMain.getRecommenderList().get(selectedIndex));
	}

	/**
	 * Blocks all visual components of panel.
	 * @see ViewRecommendersPanel
	 */
	public void blockAllComponents() {
		this.view.setEnabledAll(false);
	}
	
	
	/**
	 * UnBlocks all visual components of panel.
	 */
	public void unBlockAllComponents() {
		this.view.setEnabledAll(true);
	}	
	
	
	/**
	 * Get the list of {@link Recommender} from {@link ControllerMain}.</br>
	 * Each of the obtained {@link Recommender} are manipulable through its {@link IRecommender} interface.
	 * @return	list of recommendation algorithm configurations.
	 * @see		ControllerMain
	 * @see		IControllerMain
	 */
	public List<IRecommender> getRecommenderList() {
		return this.controllerMain.getRecommenderList();
	}	

	
	/**
	 * Set the list of {@link Recommender} from {@link ControllerMain}.</br>
	 * Each of the saved {@link Recommender} are manipulable through its {@link IRecommender} interface.
	 * @param	recommenderList	list of recommendation algorithm configurations.
	 * @see		ControllerMain
	 * @see		IControllerMain
	 */
	public void setRecommenderList(List<IRecommender> recommenderList) {
		this.view.setRecommenderList(recommenderList);
	}
    
	
	
	/**
	 * Get View of this controller</br>
	 * This method is only used for realize unit testing.
	 * @return IViewRecommendersPanel
	 */
	public IViewRecommendersPanel GetView()
	{
		return this.view;
	}	
	
}

